;; netdict.el --- lookup words from internet dictionary
;;
;; Author: 隐星魂 <roy.sun@starsoul.tech>
;; Copyright (C) 2015 隐星魂, Licensed by MIT <https://mit-license.org/>
;;
;; * Installation:
;; Copy netdict.el to your load-path and add following statement to your .emacs:
;; (require 'netdict)
;;
;; then M-x netdict-mode to use this plugin.
;; If you want to autoload the plugin, add following statement to your .emacs:
;; (global-netdict-mode 1)
;;
;; * 安装
;; 拷贝netdict.el到你的load-path路径中，然后在你的.emacs配置文件中增加：
;; (require 'netdict)
;;
;; 在emacs中可以使用 M-x netdict-mode 来启动此插件
;; 也可以配置为自动启动，在.emacs中增加：
;; (global-netdict-mode 1)
;; 默认浏览器：eww 词典：海词词典(dict-cn)
;; 如果需要修改浏览器或词典，配置如下
;; (setq netdict-browser "w3m") ;; 设置浏览器为w3m
;; ** 目前支持的浏览器取值：
;;    w3m: "w3m"
;;    eww: "eww"
;; (setq netdict-url bing-dict) ;; 设置词典为bing词典
;; ** 目前支持的词典取值：
;;    海词: dict-cn
;;    必应: bing-dict
;; (global-netdict-mode 1) ;;设置完成后再开启模式
;;
;; * 热键
;; M-s M-d h 查询光标处的单词
;; M-s M-d w 从minibuffer输入单词并查询
;;

(defconst dict-cn "http://dict.cn/" "海词词典")
(defconst bing-dict "http://cn.bing.com/dict/search?q=" “必应词典”)

(defgroup netdict nil
  "Group for netdict minor mode."
  :group 'tools
  :prefix "netdict-")

(defvar netdict-mode nil "Non-nil if netdict mode is enabled.")
(make-variable-buffer-local 'netdict-mode)
(defvar netdict-mode-hook nil "netdict minor mode hook")
(defvar netdict-url dict-cn "Net dictionary url")
(defconst bw-w3m-buf "*w3m*")
(defconst bw-w3m-cmd 'w3m-goto-url)
(defconst bw-eww-buf "*eww*")
(defconst bw-eww-cmd 'eww)
(defvar netdict-browser-buf bw-eww-buf "default browser buffer name")
(defvar netdict-browser-cmd bw-eww-cmd "cmd to launch browser")
(defvar netdict-browser "eww" "default browser")

(defvar netdict-mode-map (make-sparse-keymap)
  "Keymap used in netdict mode.")
(setq netdict-mode-map-prefix (make-sparse-keymap))
(define-prefix-command 'netdict-mode-map-cmd 'netdict-mode-map)
(progn
  (define-key netdict-mode-map-prefix (kbd "M-s M-d") 'netdict-mode-map-cmd))
(progn
  (define-key netdict-mode-map (kbd "h") 'netdict-search-word-from-here)
  (define-key netdict-mode-map (kbd "w") 'netdict-search-word))

(defun netdict-current-word ()
  "Return word at current point in buffer."
  (let (start end current-word)
    (skip-chars-backward "A-Za-z0-9")
    (setq start (point))
    (skip-chars-forward "A-Za-z9-9")
    (setq end (point))
    (setq current-word (buffer-substring start end))))

(defun netdict-search-word-from-here ()
  "Search current word in net dictionary."
  (interactive)
  (save-restriction
    (let (word)
      (setq word (netdict-current-word))
      (funcall netdict-browser-cmd (concat netdict-url word))
      (if (not (string= (buffer-name) netdict-browser-buf))
          (switch-to-buffer-other-window netdict-browser-buf))
      (sit-for 1))))

(defun netdict-search-word ()
  "Search current word in net dictionary."
  (interactive)
  (save-restriction
    (let (word input prompt)
      (setq word (netdict-current-word))
      (if word
          (setq prompt (concat "word: (default " word ") "))
        (setq prompt "word: "))
      (setq input (read-from-minibuffer prompt))
      (if (not (equal "" input))
          (setq word input))
      (funcall netdict-browser-cmd (concat netdict-url word))
      (if (not (string= (buffer-name) netdict-browser-buf))
          (switch-to-buffer-other-window netdict-browser-buf))
      (sit-for 1))))

(define-minor-mode netdict-mode
  "Minor mode to lookup netdict"
  1 " hl-p" netdict-mode-map-prefix
  :global t
  :group 'netdict
  (if (string= netdict-browser "eww")
      (progn
        (setq netdict-browser-buf bw-eww-buf)
        (setq netdict-browser-cmd bw-eww-cmd)))
  (if (string= netdict-browser "w3m")
      (progn
        (setq netdict-browser-buf bw-w3m-buf)
        (setq netdict-browser-cmd bw-w3m-cmd)))
  (run-hooks 'netdict-mode-hook))

(define-globalized-minor-mode global-netdict-mode
  netdict-mode
  (lambda () (netdict-mode 1)))

(provide 'netdict)
